package com.logic.modular.game.player.hero.service;

import com.logic.comment.exection.InfoTips;
import com.comment.exception.ServiceException;
import com.comment.pojo.domain.EquipAttribute;
import com.logic.config.netty.web.service.MessageService;
import com.logic.modular.game.battle.info.base.PvpPlayerInfo;
import com.logic.modular.game.battle.info.base.PvpPlayerInfoServiceImpl;
import com.logic.modular.game.player.bag.service.BagItemServiceImpl;
import com.logic.modular.game.player.bag.service.PlayerPropType2ServiceImpl;
import com.logic.modular.game.player.bag.service.PlayerPropType4ServiceImpl;
import com.comment.pojo.domain.logic.domain.PvpRanks;
import com.comment.pojo.domain.logic.domain.PlayerHero;
import com.logic.modular.game.statistical.service.impl.PlayerStatisticalPool2ServiceImpl;
import com.logic.modular.game.statistical.service.impl.PlayerStatisticalPoolServiceImpl;
import com.logic.modular.game.player.skill.PlayerSkillServiceImpl;
import com.comment.pojo.domain.logic.domain.PlayerSkill;
import com.logic.modular.game.player.info.service.PlayerStatusServiceImpl;
import com.logic.modular.game.PvpCity;
import com.logic.modular.game.player.match.service.PvpCityServiceImpl;
import com.logic.modular.game.player.match.service.PvpRanksServiceImpl;
import com.comment.pojo.domain.logic.core.CoreAccountConfig;
import com.logic.modular.gameCore.config.service.impl.CoreAccountConfigServiceImpl;
import com.comment.pojo.domain.logic.core.CoreExperience;
import com.logic.modular.gameCore.cultivate.exp.CoreExperienceServiceImpl;
import com.comment.pojo.domain.logic.core.CoreHero;
import com.logic.modular.gameCore.cultivate.hero.service.CoreHeroServiceImpl;
import com.comment.pojo.domain.logic.core.CoreHeroStar;
import com.logic.modular.gameCore.cultivate.hero.service.CoreHeroStarServiceImpl;
import com.comment.pojo.domain.logic.core.CoreSkillStar;
import com.logic.modular.gameCore.cultivate.skill.controller.CoreSkillStarServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.comment.pojo.domain.logic.domain.PlayerHero.recalculateAttributes;

/**
 * 游戏账户武将数据(PlayerHero)表服务实现类
 *
 * @author cxy
 * @since 2024-07-18 10:48:50
 */
@Slf4j
@Service
public class PlayerHeroServiceImpl extends PlayerHeroBaseServiceImpl implements PlayerHeroService {
    @Resource
    private PvpCityServiceImpl pvpCityServiceImpl;
    @Resource
    private CoreHeroStarServiceImpl coreHeroStarServiceImpl;
    @Resource
    private PlayerStatusServiceImpl playerStatusService;
    @Resource
    private CoreSkillStarServiceImpl coreSkillStarServiceImpl;
    @Resource
    private PlayerSkillServiceImpl playerSkillServiceImpl;
    @Resource
    @Lazy
    private PvpRanksServiceImpl pvpRanksService;
    @Resource
    private PvpPlayerInfoServiceImpl pvpPlayerInfoServiceImpl;
    @Resource
    private BagItemServiceImpl bagItemService;
    @Resource
    private PlayerPropType2ServiceImpl playerPropType2Service;
    @Resource
    private PlayerPropType2ServiceImpl playerPropType2ServiceImpl;
    @Resource
    private PlayerPropType4ServiceImpl playerPropType4ServiceImpl;
    @Autowired
    private PlayerStatisticalPoolServiceImpl playerStatisticalPoolServiceImpl;
    @Autowired
    private PlayerStatisticalPool2ServiceImpl playerStatisticalPool2ServiceImpl;


    /**
     * 登录赠送
     */
    public void registerInit(Long playerId) {
        CoreAccountConfig playerGiveaway = CoreAccountConfigServiceImpl.getCache(1L);
        Map<Long, Integer> heroMap = playerGiveaway.getHero();
        heroMap.forEach((heroId, value) -> obtainHero(playerId, heroId, value));
    }

    public void updateRankOrder(Long playerId, Long heroId, int i) {
        PlayerHero playerHero = selectCache(playerId, heroId);
        if (playerHero != null) {
            playerHero.setRankOrder(i);
            updateById(playerHero);
        }
    }

    public PlayerHero buBing(
            Long playerId,
            Long coreWuJiangId,
            Long troopsQuantity
    ) {
        Long currentMatchId = playerStatusService.currentMatchId(playerId);
        PlayerHero playerHero = select(playerId, coreWuJiangId);
        if (playerHero == null) {
            throw new ServiceException("英雄不属于当前用户");
        }

        PvpRanks accountRanks = obtainPvpRanks(playerId, coreWuJiangId);
        if (accountRanks.getStatus() == 2) {
            throw new ServiceException("队伍在战斗无法补兵");
        }

        PvpCity pvpCity = pvpCityServiceImpl.getCache(
                currentMatchId, accountRanks.getCityId());
        if (pvpCity==null) {
            throw new ServiceException("城池不存在");
        }
        if (!pvpCity.getOwnerUid().equals(playerId)){
            throw new ServiceException("城池不属于当前用户");
        }

        Long currentForce = playerHero.getCurrentForce();
        long readyArmy = pvpCity.getReadyArmy();
        Long maxReadyArmy = (long) (playerHero.getDes() * 32);

        if (troopsQuantity > maxReadyArmy) {

            throw new ServiceException("补兵数量不能超过武将的统率能力上限");
        }

        // 使用后 预备兵兵力
        readyArmy = currentForce + readyArmy - troopsQuantity;
        if (readyArmy < 0) {
            MessageService.sendMessageToUser(playerId, MessageService.updateJsonObject("pvpCity", pvpCity));
            throw new ServiceException("城池预备兵数量不足");
        }
        // 更新英雄兵力
        playerHero.setCurrentForce(troopsQuantity);
        this.updateById(playerHero);

        // 更新城池预备兵
        pvpCity.setReadyArmy(readyArmy);
        pvpCityServiceImpl.update(pvpCity);
        return playerHero;
    }

    public void buBingNoPay(
            Long playerId,
            Long coreWuJiangId,
            Long troopsQuantity
    ) {
        PlayerHero playerHero = select(playerId, coreWuJiangId);
        if (playerHero == null) {
            throw new ServiceException("英雄不属于当前用户");
        }

        // 更新英雄兵力
        playerHero.setCurrentForce(troopsQuantity);
        this.updateById(playerHero);
    }

    private PvpRanks obtainPvpRanks(Long playerId, Long coreWuJiangId) {
        List<PvpRanks> collect = pvpRanksService.obtainPvpRanKs(playerId).stream()
                .filter(item -> item.obtainCoreHeroIds().contains(coreWuJiangId))
                .collect(Collectors.toList());
        if (collect.isEmpty()) {
            throw new ServiceException("队伍不存在");
        }
        return collect.get(0);
    }

    public PlayerHero obtainHero(Long playerId, Long coreHeroId, Integer quantity) {
        PlayerHero accountHero = select(playerId, coreHeroId);
        CoreHero coreHero = CoreHeroServiceImpl.getCache(coreHeroId);
        CoreHeroStar coreHeroStar = CoreHeroStarServiceImpl.getCache(coreHeroId, 0);
        CoreSkillStar coreSkillStar = coreSkillStarServiceImpl.get(coreHero.getSkill());
        if (accountHero == null) {
            accountHero = new PlayerHero();
            accountHero.setUid(playerId);
            accountHero.setCoreHeroId(coreHeroId);
            accountHero.setLevel(1);
            accountHero.setStar(0);
            accountHero.setQuality(coreHero.getQualityLv());
            // 查经验表
            CoreExperience coreExperience = CoreExperienceServiceImpl.getCache(1, 1);
            accountHero.setNextExp(coreExperience.getExp());
            accountHero.setName(coreHero.getName());
            ////////
            accountHero.setSkill(coreSkillStar.getId());
            ////////
            recalculateAttributes(accountHero, coreHero, coreHeroStar);

            save(accountHero);
            quantity = quantity - 1;
            if (quantity > 0) {
                heroToProp(playerId, coreHeroId, quantity);
            }
            playerStatisticalPool2ServiceImpl.flush22(playerId);
        } else {
            // 转化为信物
            heroToProp(playerId, coreHeroId, 1);
            log.info("玩家{}武将{}已转化为信物", playerId, accountHero.getName());
        }
        return accountHero;
    }




    private void heroToProp(Long playerId, Long coreHeroId, Integer quantity) {
        String prop = coreHeroStarServiceImpl.getProp(coreHeroId);
        if (!prop.contains("&")) {
            throw new InfoTips("当前武将不存在信物");
        }
        Long propId = Long.valueOf(prop.split("&")[0]);
        // 添加物品
        bagItemService.obtainBagItem(playerId, propId, BigDecimal.valueOf(quantity));
    }


    public PvpRanks clickBattle(
            Long playerId,
            Long matchId,
            Integer rankNo,
            Long targetCityId
    ) {
        PvpRanks pvpRanks = pvpRanksService.select(playerId, Math.toIntExact(rankNo));

        if (pvpRanks == null) {
            throw new ServiceException("请先编队");
        }
        if (pvpRanks.getHeroId1() == 0 && pvpRanks.getHeroId2() == 0 && pvpRanks.getHeroId3() == 0) {
            throw new ServiceException("队伍不能为空");
        }
        // 检验城池所属
        Long uid = pvpRanks.getUid();
        Long cityId = pvpRanks.getCityId();

        PvpPlayerInfo pvpPlayerInfo = pvpPlayerInfoServiceImpl.get(matchId, uid);
        Set<Long> currentCity = pvpPlayerInfo.getCurrentCity();
        if (!currentCity.contains(targetCityId)) {
            throw new ServiceException("当前城池不属于当前用户");
        }
        // 更新
        pvpRanks.setStatus(1);
        pvpRanks.setCityId(targetCityId);
        pvpRanksService.updateById(pvpRanks);
        return pvpRanks;
    }

    // 升星
    @Transactional
    public PlayerHero risingStar(Long uid, Long playerHeroId) {
        PlayerHero playerHero = getById(playerHeroId);
        if (playerHero == null) {
            throw new ServiceException("玩家武将:" + playerHeroId + "不存在");
        }
        Long coreHeroId = playerHero.getCoreHeroId();
        if (playerHero.getStar() == 5) {
            return playerHero;
        }

        // 获取消耗信息
        Integer star = playerHero.getStar();
        int nextStar = star + 1;
        Long nextSkillStarId = playerHero.getSkill() + 1;

        CoreHeroStar coreHeroStar = CoreHeroStarServiceImpl.getCache(coreHeroId, nextStar);
        Long propId = coreHeroStar.getPropId();
        Long propNum = coreHeroStar.getPropNum();

        // 消耗物品
        boolean b = playerPropType2Service.tryPayProp(uid, propId, BigDecimal.valueOf(propNum));

        if (b) {
            try {
                // 基础数据
                CoreHero coreHero = CoreHeroServiceImpl.getCache(coreHeroId);
                Integer qualityLv = coreHero.getQualityLv();
                if (star < qualityLv) {
                    playerHero.setStar(nextStar);
                    playerHero.setSkill(nextSkillStarId);
                    recalculateAttributes(playerHero, coreHero, coreHeroStar);
                    updateById(playerHero);
                    // 记录
                    playerStatisticalPool2ServiceImpl.logRisingStar(playerHero.getUid());
                } else {
                    throw new ServiceException(String.format("武将:%s,已到达上限星阶:%d", playerHero.getName(), star));
                }
            } catch (Exception e) {
                bagItemService.obtainBagItem(uid, propId, BigDecimal.valueOf(propNum));
                throw e;
            }
        } else {
            throw new ServiceException("道具不足", propId);
        }
        return playerHero;
    }

    @Transactional
    public PlayerHero levelUp(
            Long uid,
            Long playerHeroId,
            Long corePropNum
    ) {
        Long corePropId = 2006L;
        long useValue = 1000L;
        PlayerHero playerHero = getById(playerHeroId);
        if (playerHero == null) {
            throw new ServiceException("武将不存在");
        }
        boolean b = playerPropType2ServiceImpl.tryPayProp(uid, corePropId, BigDecimal.valueOf(corePropNum));
        if (b) {
            playerHero.currentExp += useValue * corePropNum;
            updateById(playerHero);
            playerHero = getById(playerHeroId);
        } else {
            throw new ServiceException("道具不足", corePropId);
        }
        CoreHero coreHero = CoreHeroServiceImpl.getCache(playerHero.getCoreHeroId());
        // 获取成长属性
        CoreHeroStar coreHeroStar = CoreHeroStarServiceImpl.getCache(playerHero.getCoreHeroId(), playerHero.getStar());


        int level = CoreExperienceServiceImpl.obtainLeave(2, playerHero.getCurrentExp());
        playerHero.setLevel(level);
        long nextExp = CoreExperienceServiceImpl.obtainNextLeaveExp(2, playerHero.getLevel() + 1) - playerHero.getCurrentExp();
        playerHero.setNextExp(nextExp);
        // 重新计算属性
        playerHero.recalculateAttributes1(coreHero, coreHeroStar);
        // 更新
        updateById(playerHero);
        playerHero = getById(playerHeroId);

        playerStatisticalPool2ServiceImpl.flush20(uid);
        return playerHero;
    }


    @Transactional
    public PlayerHero wearEquipment(
            Long uid,
            @NotNull(message = "武将id不能为空") Long coreHeroId,
            Long bagItemId
    ) {
        PlayerHero playerHero = select(uid, coreHeroId);
        // 恢复物品
        boolean b = playerPropType4ServiceImpl.tryEquipArms(uid, bagItemId, playerHero.getId());
        if (b) {
            EquipAttribute equipAttribute = playerPropType4ServiceImpl.obtainEquipAttribute(uid, bagItemId);
            playerHero = PlayerHero.equip(playerHero, equipAttribute);
            updateById(playerHero);
        } else {
            throw new ServiceException("穿戴装备失败");
        }
        return playerHero;
    }

    /**
     * 卸下装备
     */
    public PlayerHero unloadEquipment(
            Long uid,
            Long coreHeroId,
            Long bagItemId
    ) {
        PlayerHero playerHero = select(uid, coreHeroId);
        // 恢复物品
        boolean b = playerPropType4ServiceImpl.tryUnEquipArms(uid, bagItemId, playerHero.getId());
        if (b) {
            EquipAttribute equipAttribute = playerPropType4ServiceImpl.obtainEquipAttribute(uid, bagItemId);
            playerHero = PlayerHero.unEquip(playerHero, equipAttribute);
            updateById(playerHero);
        }
        return playerHero;
    }

    public PlayerHero wearSkill(
            Long uid,
            Long playerHeroId,
            Integer skillSlot,
            Long coreSkillStarId
    ) {
        PlayerHero playerHero = getById(playerHeroId);
        if (playerHero == null) {
            throw new ServiceException("武将不存在");
        }
        if (!playerHero.getUid().equals(uid)) {
            throw new ServiceException("玩家数据不匹配");
        }
        Long skillSlot1 = playerHero.getSkillSlot1();
        Long skillSlot2 = playerHero.getSkillSlot2();
        if (skillSlot == 1) {
            if (skillSlot1 != 0) {
                throw new ServiceException("卡槽已满");
            }
            PlayerSkill playerSkill = playerSkillServiceImpl.selectByCoreSkillStarId(uid, coreSkillStarId);
            if (playerSkill == null) {
                throw new ServiceException("当前技能不存在");
            }
            if (playerSkill.getStatus() == 2) {
                throw new ServiceException("当前技能已占用");
            }
            playerSkill.setStatus(2);
            boolean b = playerSkillServiceImpl.updateById(playerSkill);
            if (b) {
                playerHero.setSkillSlot1(coreSkillStarId);
                updateById(playerHero);
                playerHero = getById(playerHeroId);
            }
        }
        if (skillSlot == 2) {
            if (skillSlot2 != 0) {
                throw new ServiceException("卡槽已满");
            }
            PlayerSkill playerSkill = playerSkillServiceImpl.selectByCoreSkillStarId(uid, coreSkillStarId);
            if (playerSkill == null) {
                throw new ServiceException("当前技能不存在");
            }
            playerSkill.setStatus(2);
            boolean b = playerSkillServiceImpl.updateById(playerSkill);
            if (b) {
                playerHero.setSkillSlot2(coreSkillStarId);
                updateById(playerHero);
                playerHero = getById(playerHeroId);
            }
        }
        return playerHero;
    }

    public PlayerHero unloadSkill(
            Long uid,
            Long playerHeroId,
            Integer skillSlot
    ) {
        PlayerHero playerHero = getById(playerHeroId);
        if (skillSlot == 1) {
            Long skillSlot1 = playerHero.getSkillSlot1();
            if (skillSlot1 == 0) {
                throw new ServiceException("卡槽不存在技能");
            }
            PlayerSkill playerSkill = playerSkillServiceImpl.selectByCoreSkillStarId(uid, skillSlot1);
            if (playerSkill == null) {
                throw new ServiceException("当前技能不存在");
            }
            playerSkill.setStatus(1);
            boolean b = playerSkillServiceImpl.updateById(playerSkill);
            if (b) {
                playerHero.setSkillSlot1(0L);
                updateById(playerHero);
                playerHero = getById(playerHeroId);
            }
        }
        if (skillSlot == 2) {
            Long skillSlot2 = playerHero.getSkillSlot2();
            if (skillSlot2 == 0) {
                throw new ServiceException("卡槽不存在技能");
            }
            PlayerSkill playerSkill = playerSkillServiceImpl.selectByCoreSkillStarId(uid, skillSlot2);
            if (playerSkill == null) {
                throw new ServiceException("当前技能不存在");
            }
            playerSkill.setStatus(1);
            boolean b = playerSkillServiceImpl.updateById(playerSkill);
            if (b) {
                playerHero.setSkillSlot2(0L);
                updateById(playerHero);
                playerHero = getById(playerHeroId);
            }
        }
        return playerHero;
    }

    public PlayerHero obtainTroops(Long id, Long num) {
        PlayerHero byId = getById(id);
        byId.addCurrentForce(num);
        boolean b = byId.updateById();
        if (b) {
            savaCache(byId);
        }
        return byId;
    }
}